package serv_impl

import (
	"context"
	"encoding/json"
	"fmt"

	"atomgit.com/openlinksaas/proto-gen-go.git/k8s_proxy_api"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func (apiImpl *K8SProxyApiImpl) GetResource(ctx context.Context, req *k8s_proxy_api.GetResourceRequest) (*k8s_proxy_api.GetResourceResponse, error) {
	//检查权限
	tokenInfo, err := getTokenInfo(apiImpl.linkSaasAddr, req.Token)
	if err != nil {
		return nil, err
	}
	k8sClientSet, err := getK8sClientSet(apiImpl.kubeConfigFile)
	if err != nil {
		return nil, err
	}
	{
		if req.Namespace == "" {
			return &k8s_proxy_api.GetResourceResponse{
				Code:   k8s_proxy_api.GetResourceResponse_CODE_NO_PERMISSION,
				ErrMsg: "必须指定命名空间",
			}, nil
		}
		client := k8sClientSet.CoreV1().Namespaces()
		res, err := client.Get(ctx, req.Namespace, metav1.GetOptions{})
		if err != nil {
			return nil, err
		}
		if res.Labels[PROJECT_LABEL] != tokenInfo.ProjectId {
			return &k8s_proxy_api.GetResourceResponse{
				Code:   k8s_proxy_api.GetResourceResponse_CODE_NO_PERMISSION,
				ErrMsg: "命名空间没有关联项目",
			}, nil
		}
	}
	//只支持pod,deployment和statefulset
	if req.ResourceType == k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_POD {
		client := k8sClientSet.CoreV1().Pods(req.Namespace)
		res, err := client.Get(ctx, req.ResourceName, metav1.GetOptions{})
		if err != nil {
			return nil, err
		}
		jsonData, err := json.Marshal(res)
		if err != nil {
			return nil, err
		}
		return &k8s_proxy_api.GetResourceResponse{
			Code:    k8s_proxy_api.GetResourceResponse_CODE_OK,
			Payload: string(jsonData),
		}, nil
	} else if req.ResourceType == k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_DEPLOYMENT {
		client := k8sClientSet.AppsV1().Deployments(req.Namespace)
		res, err := client.Get(ctx, req.ResourceName, metav1.GetOptions{})
		if err != nil {
			return nil, err
		}
		jsonData, err := json.Marshal(res)
		if err != nil {
			return nil, err
		}
		return &k8s_proxy_api.GetResourceResponse{
			Code:    k8s_proxy_api.GetResourceResponse_CODE_OK,
			Payload: string(jsonData),
		}, nil
	} else if req.ResourceType == k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_STATEFULSET {
		client := k8sClientSet.AppsV1().StatefulSets(req.Namespace)
		res, err := client.Get(ctx, req.ResourceName, metav1.GetOptions{})
		if err != nil {
			return nil, err
		}
		jsonData, err := json.Marshal(res)
		if err != nil {
			return nil, err
		}
		return &k8s_proxy_api.GetResourceResponse{
			Code:    k8s_proxy_api.GetResourceResponse_CODE_OK,
			Payload: string(jsonData),
		}, nil
	}

	return &k8s_proxy_api.GetResourceResponse{
		Code:   k8s_proxy_api.GetResourceResponse_CODE_NO_PERMISSION,
		ErrMsg: "只能获取pod,deployment和statefulset",
	}, nil
}

func (apiImpl *K8SProxyApiImpl) ListResource(ctx context.Context, req *k8s_proxy_api.ListResourceRequest) (*k8s_proxy_api.ListResourceResponse, error) {
	//检查权限
	tokenInfo, err := getTokenInfo(apiImpl.linkSaasAddr, req.Token)
	if err != nil {
		return nil, err
	}

	k8sClientSet, err := getK8sClientSet(apiImpl.kubeConfigFile)
	if err != nil {
		return nil, err
	}
	if req.ResourceType != k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_NAMESPACE {
		if req.Namespace == "" {
			return &k8s_proxy_api.ListResourceResponse{
				Code:   k8s_proxy_api.ListResourceResponse_CODE_NO_PERMISSION,
				ErrMsg: "必须指定命名空间",
			}, nil
		}
		client := k8sClientSet.CoreV1().Namespaces()
		res, err := client.Get(ctx, req.Namespace, metav1.GetOptions{})
		if err != nil {
			return nil, err
		}
		if res.Labels[PROJECT_LABEL] != tokenInfo.ProjectId {
			return &k8s_proxy_api.ListResourceResponse{
				Code:   k8s_proxy_api.ListResourceResponse_CODE_NO_PERMISSION,
				ErrMsg: "命名空间没有关联项目",
			}, nil
		}
	}
	if req.ResourceType == k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_NAMESPACE {
		client := k8sClientSet.CoreV1().Namespaces()
		res, err := client.List(ctx, metav1.ListOptions{
			LabelSelector: fmt.Sprintf("%s=%s", PROJECT_LABEL, tokenInfo.ProjectId),
		})
		if err != nil {
			return nil, err
		}
		jsonData, err := json.Marshal(res)
		if err != nil {
			return nil, err
		}
		return &k8s_proxy_api.ListResourceResponse{
			Code:    k8s_proxy_api.ListResourceResponse_CODE_OK,
			Payload: string(jsonData),
		}, nil
	} else if req.ResourceType == k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_POD {
		client := k8sClientSet.CoreV1().Pods(req.Namespace)
		res, err := client.List(ctx, metav1.ListOptions{
			LabelSelector: req.LabelSelector,
		})
		if err != nil {
			return nil, err
		}
		jsonData, err := json.Marshal(res)
		if err != nil {
			return nil, err
		}
		return &k8s_proxy_api.ListResourceResponse{
			Code:    k8s_proxy_api.ListResourceResponse_CODE_OK,
			Payload: string(jsonData),
		}, nil
	} else if req.ResourceType == k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_DEPLOYMENT {
		client := k8sClientSet.AppsV1().Deployments(req.Namespace)
		res, err := client.List(ctx, metav1.ListOptions{
			LabelSelector: req.LabelSelector,
		})
		if err != nil {
			return nil, err
		}
		jsonData, err := json.Marshal(res)
		if err != nil {
			return nil, err
		}
		return &k8s_proxy_api.ListResourceResponse{
			Code:    k8s_proxy_api.ListResourceResponse_CODE_OK,
			Payload: string(jsonData),
		}, nil
	} else if req.ResourceType == k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_STATEFULSET {
		client := k8sClientSet.AppsV1().StatefulSets(req.Namespace)
		res, err := client.List(ctx, metav1.ListOptions{
			LabelSelector: req.LabelSelector,
		})
		if err != nil {
			return nil, err
		}
		jsonData, err := json.Marshal(res)
		if err != nil {
			return nil, err
		}
		return &k8s_proxy_api.ListResourceResponse{
			Code:    k8s_proxy_api.ListResourceResponse_CODE_OK,
			Payload: string(jsonData),
		}, nil
	}

	return &k8s_proxy_api.ListResourceResponse{
		Code:   k8s_proxy_api.ListResourceResponse_CODE_NO_PERMISSION,
		ErrMsg: "未知类型资源",
	}, nil
}

func (apiImpl *K8SProxyApiImpl) UpdateImage(ctx context.Context, req *k8s_proxy_api.UpdateImageRequest) (*k8s_proxy_api.UpdateImageResponse, error) {
	tokenInfo, err := getTokenInfo(apiImpl.linkSaasAddr, req.Token)
	if err != nil {
		return nil, err
	}
	k8sClientSet, err := getK8sClientSet(apiImpl.kubeConfigFile)
	if err != nil {
		return nil, err
	}
	{
		if req.Namespace == "" {
			return &k8s_proxy_api.UpdateImageResponse{
				Code:   k8s_proxy_api.UpdateImageResponse_CODE_NO_PERMISSION,
				ErrMsg: "必须指定命名空间",
			}, nil
		}
		client := k8sClientSet.CoreV1().Namespaces()
		res, err := client.Get(ctx, req.Namespace, metav1.GetOptions{})
		if err != nil {
			return nil, err
		}
		if res.Labels[PROJECT_LABEL] != tokenInfo.ProjectId {
			return &k8s_proxy_api.UpdateImageResponse{
				Code:   k8s_proxy_api.UpdateImageResponse_CODE_NO_PERMISSION,
				ErrMsg: "命名空间没有关联项目",
			}, nil
		}
	}

	if !tokenInfo.Admin {
		userPerm := apiImpl.getResourceUserPerm(ctx, req.Namespace, req.ResourceType, req.ResourceName, tokenInfo.MemberUserId)
		if !userPerm.UpdateImage {
			return &k8s_proxy_api.UpdateImageResponse{
				Code:   k8s_proxy_api.UpdateImageResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
			}, nil
		}
	}

	if req.ResourceType == k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_DEPLOYMENT {
		client := k8sClientSet.AppsV1().Deployments(req.Namespace)
		target, err := client.Get(ctx, req.ResourceName, metav1.GetOptions{})
		if err != nil {
			return nil, err
		}
		for index, container := range target.Spec.Template.Spec.Containers {
			if container.Name == req.ContainerName {
				container.Image = req.Image
				target.Spec.Template.Spec.Containers[index] = container
			}
		}
		_, err = client.Update(ctx, target, metav1.UpdateOptions{})
		if err != nil {
			return nil, err
		}
		return &k8s_proxy_api.UpdateImageResponse{
			Code: k8s_proxy_api.UpdateImageResponse_CODE_OK,
		}, nil
	} else if req.ResourceType == k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_STATEFULSET {
		client := k8sClientSet.AppsV1().StatefulSets(req.Namespace)
		target, err := client.Get(ctx, req.ResourceName, metav1.GetOptions{})
		if err != nil {
			return nil, err
		}
		for index, container := range target.Spec.Template.Spec.Containers {
			if container.Name == req.ContainerName {
				container.Image = req.Image
				target.Spec.Template.Spec.Containers[index] = container
			}
		}
		_, err = client.Update(ctx, target, metav1.UpdateOptions{})
		if err != nil {
			return nil, err
		}
		return &k8s_proxy_api.UpdateImageResponse{
			Code: k8s_proxy_api.UpdateImageResponse_CODE_OK,
		}, nil
	}

	return &k8s_proxy_api.UpdateImageResponse{
		Code:   k8s_proxy_api.UpdateImageResponse_CODE_NO_PERMISSION,
		ErrMsg: "未知类型资源",
	}, nil
}

func (apiImpl *K8SProxyApiImpl) UpdateScale(ctx context.Context, req *k8s_proxy_api.UpdateScaleRequest) (*k8s_proxy_api.UpdateScaleResponse, error) {
	tokenInfo, err := getTokenInfo(apiImpl.linkSaasAddr, req.Token)
	if err != nil {
		return nil, err
	}
	k8sClientSet, err := getK8sClientSet(apiImpl.kubeConfigFile)
	if err != nil {
		return nil, err
	}
	{
		if req.Namespace == "" {
			return &k8s_proxy_api.UpdateScaleResponse{
				Code:   k8s_proxy_api.UpdateScaleResponse_CODE_NO_PERMISSION,
				ErrMsg: "必须指定命名空间",
			}, nil
		}
		client := k8sClientSet.CoreV1().Namespaces()
		res, err := client.Get(ctx, req.Namespace, metav1.GetOptions{})
		if err != nil {
			return nil, err
		}
		if res.Labels[PROJECT_LABEL] != tokenInfo.ProjectId {
			return &k8s_proxy_api.UpdateScaleResponse{
				Code:   k8s_proxy_api.UpdateScaleResponse_CODE_NO_PERMISSION,
				ErrMsg: "命名空间没有关联项目",
			}, nil
		}
	}

	if !tokenInfo.Admin {
		userPerm := apiImpl.getResourceUserPerm(ctx, req.Namespace, req.ResourceType, req.ResourceName, tokenInfo.MemberUserId)
		if !userPerm.UpdateScale {
			return &k8s_proxy_api.UpdateScaleResponse{
				Code:   k8s_proxy_api.UpdateScaleResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
			}, nil
		}
	}

	replicas := int32(req.Scale)

	if req.ResourceType == k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_DEPLOYMENT {
		client := k8sClientSet.AppsV1().Deployments(req.Namespace)
		target, err := client.Get(ctx, req.ResourceName, metav1.GetOptions{})
		if err != nil {
			return nil, err
		}
		target.Spec.Replicas = &replicas
		_, err = client.Update(ctx, target, metav1.UpdateOptions{})
		if err != nil {
			return nil, err
		}
		return &k8s_proxy_api.UpdateScaleResponse{
			Code: k8s_proxy_api.UpdateScaleResponse_CODE_OK,
		}, nil
	} else if req.ResourceType == k8s_proxy_api.RESOURCE_TYPE_RESOURCE_TYPE_STATEFULSET {
		client := k8sClientSet.AppsV1().StatefulSets(req.Namespace)
		target, err := client.Get(ctx, req.ResourceName, metav1.GetOptions{})
		if err != nil {
			return nil, err
		}
		target.Spec.Replicas = &replicas
		_, err = client.Update(ctx, target, metav1.UpdateOptions{})
		if err != nil {
			return nil, err
		}
		return &k8s_proxy_api.UpdateScaleResponse{
			Code: k8s_proxy_api.UpdateScaleResponse_CODE_OK,
		}, nil
	}

	return &k8s_proxy_api.UpdateScaleResponse{
		Code:   k8s_proxy_api.UpdateScaleResponse_CODE_NO_PERMISSION,
		ErrMsg: "未知类型资源",
	}, nil
}
